/*
 * This program (in conjunction to recv_anycast) illustrates the use of 
 * anycast triggers to lower the overhead of inserting multiple
 * triggers in i3. 
 * Usage:
 *  > recv_anycast <cfg_file.xml>
 *  > send_anycast <cfg_file.xml> <id1> <id2> <id3>
 *  (id1, id2 and id3 represents the IDs inserted by the receiver;
 *   these IDs are printed out by recv_anycast)
 *
 * In particular, in this example, instead of inserting three triggers
 * (id1, R), (id2, R), (id3, R) in i3, the receiver choses id1, id2,
 * and id3 to share the preffix with a 4th trigger (ida, R), and then
 * inserts only (ida, R) in i3; the other three triggers are inserted
 * only locally  
 */ 

#include <stdio.h>

#include "i3.h"
#include "i3_client_api.h"
#include "utils.h"


#define MY_PKT_SIZE 1024

void send_data(ID *id)
{
  struct timeval tv;
  static long    seq = 0;
  long           temp; 
  static cl_buf *clb = NULL;

  if (clb == NULL) 
    clb = cl_alloc_buf(MY_PKT_SIZE);

  printf("sending to");
  print_id(id);
  sprintf(clb->data, "The ID of this packet ends in %d", id->x[ID_LEN-1]);
  clb->data_len = strlen(clb->data) + 1; 

  /* send packet */
  cl_send(id, clb, 0);
    
  /* set timer to send next packet */
  tv.tv_sec  = 1;
  tv.tv_usec = 0;
  cl_set_timer(&tv, send_data, id);
}  


void no_matching_trigger(void *ctx_data, void *data, void *fun_ctx)
{
  ID *id = (ID *) ctx_data;
  printf("Following ID not found, ");
  print_id(id);
}

int i3_main_loop(char *cfg_file, char *idc1, char *idc2, char *idc3)
{
  ID     id1, id2, id3;
  struct timeval tv;

  /* initialize context */
  cl_init(cfg_file);

  read_id(&id1, idc1);
  read_id(&id2, idc2);
  read_id(&id3, idc3);

  /* exception when matching trigger not found */
  cl_register_callback(CL_CBK_TRIGGER_NOT_FOUND, no_matching_trigger, NULL);

  /* setup the timer to send the first packet */
  tv.tv_sec  = 1;
  tv.tv_usec = 0;
  cl_set_timer(&tv, send_data, (void *)&id1);
  tv.tv_usec = 300000;
  cl_set_timer(&tv, send_data, (void *)&id2);
  tv.tv_usec = 700000;
  cl_set_timer(&tv, send_data, (void *)&id3);

  /* loop forever */
  cl_loop();
  
  /* destroy context */
  cl_exit();
}


int main(int argc, char **argv)
{
  if (argc != 5) {
    printf("%s <cfg_file.xml> <id1> <id2> <id3>\n", argv[0]);
    exit(-1);
  }

  i3_main_loop(argv[1], argv[2], argv[3], argv[4]);
  return -1;
}
